package telas;

import inicio.Principal;

import java.awt.Dimension;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.filechooser.FileNameExtensionFilter;

import servidor.InterfaceServicos;
import utilidades.ManipulaArquivos;

/**
 * 
 * @author Douglas Borges
 * 
 */
@SuppressWarnings("serial")
public class UsuarioE extends JPanel {

  private JTextArea caArquivosSelecionados, caExecucao;

  private JButton abrirArquivo, limparArquivo, executar, encerrar;

  private JComboBox cbArquitetura;

  private Image i;

  private JLabel label;

  List<String> listNomeLinha, listEquipe, listIdentificacaoExterna, listLocalArmazenado;

  List<File> listArquivos;

  JPanel painelArquitura = new JPanel();
  JPanel painelArquivos = new JPanel();
  JPanel painelExecucao = new JPanel();

  JTextField cxFlag = new JTextField();

  Dimension screenSize = this.getToolkit().getScreenSize();
  double largura = screenSize.getWidth();
  double altura = screenSize.getHeight();

  // Coordenadas dos Paineis
  int x = 0, y = 0;
  int remX = 0, remY = 0;
  int painelExecucaoX = 0, painelExecucaoY = 200;
  int painelArquivoX = (int) ((largura / 2) + 2), painelArquivoY = 0;


  public UsuarioE() {

    super.setLayout(null);

    /**
     * Desenha o painel com os objetos da arquitetura
     */
    desenhaPainelArquitetura();

    desenhaPainelArquivo();

    desenhaPainelExecucao();

    super.setLocation(0, 0);
    super.setSize(screenSize);
    super.setVisible(true);

  }


  /**
   * Retorna o resultado do servidor para a tela
   */
  public void desenhaPainelExecucao() {

    painelExecucao.setLayout(null);
    painelExecucao.setBorder(BorderFactory.createTitledBorder("Executar o(s) Código(s)"));

    i = Toolkit.getDefaultToolkit().createImage(this.getClass().getResource("/imagens/play.jpg"));
    ImageIcon ii = new ImageIcon(i);

    executar = new JButton(ii);
    executar.setBounds(x + 10, y + 40, 50, 50);
    executar.setName("executar");
    executar.setToolTipText("Enviar ao Servidor");
    executar.addActionListener(new ControleBotoes());

    painelExecucao.add(executar);

    i = Toolkit.getDefaultToolkit().createImage(this.getClass().getResource("/imagens/stop.jpg"));
    ii = new ImageIcon(i);

    encerrar = new JButton(ii);
    encerrar.setBounds(x + 10, y + 100, 50, 50);
    encerrar.setName("stop");
    encerrar.setToolTipText("Parar Execução");
    encerrar.addActionListener(new ControleBotoes());
    painelExecucao.add(encerrar);

    caExecucao = new JTextArea();
    caExecucao.setBounds(x + 65, y + 30, (int) (largura * 0.50), (int) (altura * 0.25));
    caExecucao.setEditable(false);

    JScrollPane scroll = new JScrollPane(caExecucao);
    scroll.setBounds(x + 65, y + 30, (int) (largura * 0.50), (int) (altura * 0.25));
    painelExecucao.add(scroll);
    painelExecucao.setBounds(painelExecucaoX, painelExecucaoY, (int) ((largura) * 0.70), (int) (altura * 0.30));

    super.add(painelExecucao);
    super.repaint();
    super.revalidate();

  }


  public void desenhaPainelArquivo() {

    painelArquivos.setLayout(null);
    painelArquivos.setBorder(BorderFactory.createTitledBorder("Selecione o(s) arquivo(s) que deseja executar"));
    int posicaoX = (int) (largura * 0.30);

    caArquivosSelecionados = new JTextArea();
    caArquivosSelecionados.setBorder(BorderFactory.createTitledBorder("Arquivo(s) Selecionado(s)"));
    caArquivosSelecionados.setBounds(x + 10, y + 30, (int) (largura * 0.30), (int) (altura * 0.20));
    caArquivosSelecionados.setEditable(false);
    painelArquivos.add(caArquivosSelecionados);

    i = Toolkit.getDefaultToolkit().createImage(this.getClass().getResource("/imagens/opf.jpg"));
    ImageIcon ii2 = new ImageIcon(i);

    abrirArquivo = new JButton(ii2);
    abrirArquivo.setBounds(x + posicaoX + 20, y + 30, 50, 50);
    abrirArquivo.setName("abrirArquivo");
    abrirArquivo.setToolTipText("Abrir arquivo(s) para executar");
    abrirArquivo.addActionListener(new ControleBotoes());
    painelArquivos.add(abrirArquivo);

    i = Toolkit.getDefaultToolkit().createImage(this.getClass().getResource("/imagens/cancela.jpg"));
    ii2 = new ImageIcon(i);

    limparArquivo = new JButton(ii2);
    limparArquivo.setBounds(x + posicaoX + 20, y + 85, 50, 50);
    limparArquivo.setName("limparArquivo");
    limparArquivo.setToolTipText("Limpar Arquivo(s) Selecionado(s)");
    limparArquivo.addActionListener(new ControleBotoes());
    painelArquivos.add(limparArquivo);

    painelArquivos.setBounds(painelArquivoX, painelArquivoY, (int) ((largura / 2) * 0.9), 190);

    super.add(painelArquivos);
    this.repaint();
    this.revalidate();

  }


  public void desenhaPainelArquitetura() {

    painelArquitura.setLayout(null);
    painelArquitura.setBorder(BorderFactory.createTitledBorder("Selecione a arquitetura que deseja executar"));

    cbArquitetura = new JComboBox();
    cbArquitetura.setBorder(BorderFactory.createTitledBorder("Arquitetura"));
    cbArquitetura.setBounds(x + 10, y + 30, (int) ((largura / 2) * 0.40), 45);
    cbArquitetura.addItem("Linguagem C");
    cbArquitetura.addItem("Linguagem CUDA");
    cbArquitetura.addItem("Linguagem OpenCL");

    painelArquitura.add(cbArquitetura);

    int posicaoX = (int) ((largura / 2) * 0.40);
    i = Toolkit.getDefaultToolkit().createImage(this.getClass().getResource("/imagens/lingc.jpg"));
    ImageIcon ii = new ImageIcon(i);
    label = new JLabel(ii);
    label.setToolTipText("Linguagem C | \n Exemplo de flag para Compilação: \n ggc -o hello hello.c");// TODO

    label.setBounds(x + posicaoX + 20, y + 20, 100, 100);
    painelArquitura.add(label);

    i = Toolkit.getDefaultToolkit().createImage(this.getClass().getResource("/imagens/cuda.jpg"));
    ii = new ImageIcon(i);
    label = new JLabel(ii);
    label.setToolTipText("Arquitetura CUDA | \n Exemplo de flag para Compilação: \n nvcc -o hello hello.cu -lstdc++");// TODO
    // Douglas
    label.setBounds(x + posicaoX + 125, y + 20, 100, 100);
    painelArquitura.add(label);

    i = Toolkit.getDefaultToolkit().createImage(this.getClass().getResource("/imagens/opencl.jpg"));
    ii = new ImageIcon(i);
    label = new JLabel(ii);
    label.setToolTipText("Arquitetura OpenCL | \n Exemplo de flag para Compilação: \n gcc (ou g++) -o hello hello.c (ou .cpp) -lOpenCL");// TODO
    // Douglas
    label.setBounds(x + posicaoX + 230, y + 20, 100, 100);
    painelArquitura.add(label);

    cxFlag = new JTextField();
    cxFlag.setBorder(BorderFactory.createTitledBorder("Flag para Compilação: (informar de forma correta junto com o nome do(s) arquivo(s)"));
    cxFlag.setBounds(x + 10, y + 130, (int) ((largura / 2) * 0.80), 45);
    painelArquitura.add(cxFlag);

    painelArquitura.setBounds(remX, remY, (int) (largura / 2), 190);

    super.add(painelArquitura);
    this.repaint();
    this.revalidate();

  }

  private class ControleBotoes implements ActionListener {
    public void actionPerformed(ActionEvent evento) {

      String nomeBt = (((JButton) ((Object) evento.getSource())).getName());

      if (nomeBt.equals("stop")) {
        caExecucao.setText("");
      }
      if (nomeBt.equals("abrirArquivo")) {
        abrirDiretorio();
      }

      else if (nomeBt.equals("limparArquivo")) {
        caArquivosSelecionados.setText("");
        listArquivos.clear();

      }
      else if (nomeBt.equals("executar")) {
        if (listArquivos.size() > 0) {
          String temp[] = listArquivos.get(listArquivos.size() - 1).getAbsolutePath().replace(File.separator, "STRINGIMPOSIVEL").split("STRINGIMPOSIVEL");
          String projeto = temp[temp.length - 2];

          if (cbArquitetura.getSelectedIndex() == 0) {
            caExecucao.setText("");
            List<StringBuilder> listOut = new ArrayList<StringBuilder>();
            try {

              for (int i = 0; i < listArquivos.size(); i++) {
                File fu = listArquivos.get(i);
                if (fu.isFile())
                  listOut.add(getFile(listArquivos.get(i)));
              }

              InterfaceServicos it = getInterfaceServicos();
              if (cxFlag.getText() == null || cxFlag.getText().isEmpty())
                JOptionPane.showMessageDialog(null, "Flag nula ou incorreta!");
              else
                caExecucao.setText(it.executeCEditado(Principal.macEndereco, projeto, cxFlag.getText(), listOut));

            }
            catch (Exception e) {
              e.printStackTrace();
            }
          }
          if (cbArquitetura.getSelectedIndex() == 1) {
            caExecucao.setText("");
            List<StringBuilder> listOut = new ArrayList<StringBuilder>();
            try {

              for (int i = 0; i < listArquivos.size(); i++) {
                File fu = listArquivos.get(i);
                if (fu.isFile())
                  listOut.add(getFile(listArquivos.get(i)));

              }
              InterfaceServicos it = getInterfaceServicos();
              if (cxFlag.getText() == null || cxFlag.getText().isEmpty())
                JOptionPane.showMessageDialog(null, "Flag nula ou incorreta!");
              else
                caExecucao.setText(it.executeCudaEditado(Principal.macEndereco, projeto, cxFlag.getText(), listOut));

            }
            catch (Exception e) {
              e.printStackTrace();
            }

          }
          if (cbArquitetura.getSelectedIndex() == 2) {
            caExecucao.setText("");
            List<StringBuilder> listOut = new ArrayList<StringBuilder>();
            try {

              for (int i = 0; i < listArquivos.size(); i++) {
                File fu = listArquivos.get(i);
                if (fu.isFile())
                  listOut.add(getFile(listArquivos.get(i)));
              }
              InterfaceServicos it = getInterfaceServicos();
              if (cxFlag.getText() == null || cxFlag.getText().isEmpty())
                JOptionPane.showMessageDialog(null, "Flag nula ou incorreta!");
              else
                caExecucao.setText(it.executeOpenclEditado(Principal.macEndereco, projeto, cxFlag.getText(), listOut));
            }
            catch (Exception e) {
              e.printStackTrace();
            }

          }

        }

      }

    }
  }


  public StringBuilder getFile(File f) {
    StringBuilder sb = new StringBuilder();
    try {

      Scanner in = new Scanner(f);
      sb.append("//" + f.getName() + "\n");
      while (in.hasNextLine()) {
        sb.append(in.nextLine()).append("\n");
      }
      in.close();

    }

    catch (Exception e) {

      System.out.println(e.getMessage());
    }
    return sb;
  }


  private final InterfaceServicos getInterfaceServicos() {
    try {
      Registry registry = LocateRegistry.getRegistry(Principal.ipServidor);
      InterfaceServicos servicosRemotos = (InterfaceServicos) registry.lookup(Principal.servidor);
      System.out.println(servicosRemotos.getStatus(Principal.macEndereco, Principal.usuario));

      return servicosRemotos;
    }
    catch (Exception e) {

      e.printStackTrace();
    }
    return null;
  }


  public void removePanel() {

    painelArquivos.removeAll();
    painelExecucao.removeAll();

    desenhaPainelArquivo();
    desenhaPainelExecucao();

    painelExecucao.repaint();
    painelExecucao.revalidate();

    painelArquivos.repaint();
    painelArquivos.revalidate();

    super.repaint();
    super.revalidate();
  }


  @SuppressWarnings("static-access")
  public void abrirDiretorio() {
    JFileChooser chooser = new JFileChooser();
    String extencao = "";

    if (cbArquitetura.getSelectedIndex() == 0 || cbArquitetura.getSelectedIndex() == 2)
      chooser.setFileFilter(new FileNameExtensionFilter(String.format("Arquivos %s", "*.c, *.cpp"), "c", "cpp"));
    if (cbArquitetura.getSelectedIndex() == 1)
      chooser.setFileFilter(new FileNameExtensionFilter(String.format("Arquivos %s", "*.cu"), "cu"));

    chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
    if (chooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
      try {
        String path = chooser.getSelectedFile().getAbsolutePath();
        if (path.contains("."))
          path = path.substring(0, path.lastIndexOf(File.separator));

        listArquivos = ManipulaArquivos.getInstance().listFiles(new File(path), false);
        for (File f : listArquivos) {
          caArquivosSelecionados.setText(caArquivosSelecionados.getText() + f.getName() + "\n");
        }
      }
      catch (Exception e) {
        e.printStackTrace();
      }
    }

  }
}